package com.laomou.password.db;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * Created by mm on 2015/1/19.
 */
public class SQLiteHelper extends SQLiteOpenHelper {
    private static final String USER_DB_NAME = "rapid.db";
    private static final HashMap<Class<?>, String> CLASS_TYPES = new HashMap<Class<?>, String>();
    private HashMap<String, Class<?>> COLUMN = new HashMap<String, Class<?>>();
    private HashMap<String, Object> COLUMN_VALUE = new HashMap<String, Object>();
    private String USER_TABLE_NAME;
    private Class<?> CLS;

    static {
        CLASS_TYPES.put(String.class, "TEXT");
        CLASS_TYPES.put(Integer.class, "INTEGER");
    }

    public SQLiteHelper(Context context, Object classObj) {
        super(context, USER_DB_NAME, null, 1);
        USER_TABLE_NAME = classObj.getClass().getSimpleName();
        registerObjectOutlet(classObj.getClass());
    }

    public SQLiteHelper(Context context, Class<?> cls) {
        super(context, USER_DB_NAME, null, 1);
        CLS = cls;
        USER_TABLE_NAME = cls.getSimpleName();
        registerObjectOutlet(cls);
    }

    public void registerObjectOutlet(Class<?> cls) {
        Field[] fields = cls.getDeclaredFields();
        if (fields != null && fields.length > 0) {
            for (Field field : fields) {
                try {
                    field.setAccessible(true);
                    IDBOutlet outlet = field.getAnnotation(IDBOutlet.class);
                    if (outlet != null) {
                        String viewId = outlet.id();
                        COLUMN.put(viewId, field.getType());
                    }
                } catch (Exception e) {
                	Log.e("SQLiteHelper", "registerDBColumn exception");
                }
            }
        }
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        StringBuilder sql = new StringBuilder();
        sql.append("CREATE TABLE " + USER_TABLE_NAME);
        sql.append(" (");
        COLUMN.remove("_index");
        sql.append("_index INTEGER PRIMARY KEY AUTOINCREMENT,");
        Iterator iterator = COLUMN.entrySet().iterator();
        while (iterator.hasNext()) {
            TreeMap.Entry entry = (TreeMap.Entry) iterator.next();
            sql.append(entry.getKey() + " " + CLASS_TYPES.get(entry.getValue()));
            sql.append(",");
        }
        sql.deleteCharAt(sql.length() - 1);
        sql.append(")");
        db.execSQL(sql.toString());
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("ALTER TABLE " + USER_TABLE_NAME + " ADD COLUMN other TEXT");
    }

    public List findAll() {
        ArrayList<Object> list = new ArrayList<Object>();
        SQLiteDatabase db = getReadableDatabase();
        Cursor c = null;
        try {
            c = db.rawQuery("SELECT * FROM " + USER_TABLE_NAME, null);
            c.moveToFirst();
            while (c.moveToNext()) {
                Object obj = CLS.newInstance();
                for(String key : COLUMN.keySet()) {
                    String value = c.getString(c.getColumnIndex(key));
                    COLUMN_VALUE.put(key, value);
                }
                Field[] fields = obj.getClass().getDeclaredFields();
                if (fields != null && fields.length > 0) {
                    for (Field field : fields) {
                        field.setAccessible(true);
                        IDBOutlet outlet = field.getAnnotation(IDBOutlet.class);
                        if (outlet != null) {
                            field.set(obj, COLUMN_VALUE.get(outlet.id()));
                        }
                    }
                }
                Log.d("CC", obj.toString());
                list.add(obj);
            }
        } catch (Exception e) {
        	Log.e("SQLiteHelper", "getData exception");
        } finally {
            if (c != null) {
                c.close();
            }
        }
        return list;
    }

    public List findAll(String sql, String[] selectionArgs) {
        SQLiteDatabase db = getReadableDatabase();
        List list = new ArrayList();
        try {
            Cursor c = db.rawQuery("SELECT * FROM " + USER_TABLE_NAME + " WHERE " + sql, selectionArgs);
            while (c.moveToNext()) {
                Object obj = CLS.newInstance();
                for(String key : COLUMN.keySet()) {
                    String value = c.getString(c.getColumnIndex(key));
                    COLUMN_VALUE.put(key, value);
                }
                Field[] fields = obj.getClass().getDeclaredFields();
                if (fields != null && fields.length > 0) {
                    for (Field field : fields) {
                        field.setAccessible(true);
                        IDBOutlet outlet = field.getAnnotation(IDBOutlet.class);
                        if (outlet != null) {
                            field.set(obj, COLUMN_VALUE.get(outlet.id()));
                        }
                    }
                }
                list.add(obj);
            }
        } catch (Exception e) {
        	Log.e("SQLiteHelper", "findAll exception");
        } finally {
            db.close();
        }
        return list;
    }


    public void delAll() {
        SQLiteDatabase db = getWritableDatabase();
        try {
            db.execSQL("DELETE FROM " + USER_TABLE_NAME);
        } catch (Exception e) {
        	Log.e("SQLiteHelper", "delAll exception");
        } finally {
            db.close();
        }
    }

    public void delAll(String sql, String[] selectionArgs) {
        SQLiteDatabase db = getWritableDatabase();
        try {
            db.execSQL("DELETE FROM " + USER_TABLE_NAME + " WHERE " + sql, selectionArgs);
        } catch (Exception e) {
        	Log.e("SQLiteHelper", "delAll exception");
        } finally {
            db.close();
        }
    }
}
